home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / language / asxsrc.arc / LKMAIN.C < prev    next >
C/C++ Source or Header  |  1989-08-25  |  9KB  |  547 lines

  1. /* lkmain.c */
  2.  
  3. /*
  4.  * (C) Copyright 1989
  5.  * All Rights Reserved
  6.  *
  7.  * Alan R. Baldwin
  8.  * 721 Berkeley St.
  9.  * Kent, Ohio  44240
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include "aslink.h"
  14.  
  15. VOID
  16. main(argc, argv)
  17. char *argv[];
  18. {
  19.     register char *p;
  20.     register c, i;
  21.     FILE *afile();
  22.  
  23.     pflag = 1;
  24.     startp = (struct lfile *) new (sizeof (struct lfile));
  25.  
  26.     for (i=1; i<argc; ++i) {
  27.         p = argv[i];
  28.         if (*p == '-') {
  29.             while (ctype[c = *(++p)] == LETTER) {
  30.                 switch(c) {
  31.  
  32.                 case 'c':
  33.                 case 'C':
  34.                     startp->f_type = F_STD;
  35.                     break;
  36.  
  37.                 case 'f':
  38.                 case 'F':
  39.                     startp->f_type = F_LNK;
  40.                     break;
  41.                     
  42.                 case 'n':
  43.                 case 'N':
  44.                     pflag = 0;
  45.                     break;
  46.  
  47.                 case 'p':
  48.                 case 'P':
  49.                     pflag = 1;
  50.                     break;
  51.  
  52.                 default:
  53.                     usage();
  54.                 }
  55.             }
  56.         } else {
  57.             if (startp->f_type == F_LNK) {
  58.                 startp->f_idp = p;
  59.             }
  60.         }
  61.     }
  62.     if (startp->f_type == NULL)
  63.         usage();
  64.     if (startp->f_type == F_LNK && startp->f_idp == NULL)
  65.         usage();
  66.  
  67.     cfp = NULL;
  68.     sfp = NULL;
  69.     filep = startp;
  70.     while (1) {
  71.         ip = ib;                    
  72.         if (getline() == 0)
  73.             break;
  74.         if (pflag && sfp != stdin)
  75.             fprintf(stdout, "%s\n", ip);
  76.         if (*ip == NULL || parse())
  77.             break;
  78.     }
  79.     fclose(sfp);
  80.     if (linkp == NULL)
  81.         usage();
  82.  
  83.     syminit();
  84.     for (pass=0; pass<2; ++pass) {
  85.         cfp = NULL;
  86.         sfp = NULL;
  87.         filep = linkp;
  88.         hp = NULL;
  89.         radix = 10;
  90.  
  91.         while (getline()) {
  92.             ip = ib;
  93.             link();
  94.         }
  95.         if (pass == 0) {
  96.             /*
  97.              * Set area base addresses.
  98.              */
  99.             setbas();
  100.             /*
  101.              * Link all area addresses.
  102.              */
  103.             lnkarea();
  104.             /*
  105.              * Process global definitions.
  106.              */
  107.             setgbl();
  108.             /*
  109.              * Check for undefined globals.
  110.              */
  111.             symdef(stderr);
  112.             /*
  113.              * Output Link Map.
  114.              */
  115.             if (mflag)
  116.                 map();
  117.             /*
  118.              * Open output file
  119.              */
  120.             if (oflag == 1)
  121.                 ofp = afile(linkp->f_idp, "ihx", 1);
  122.             if (oflag == 2)
  123.                 ofp = afile(linkp->f_idp, "s19", 1);
  124.         } else {
  125.             reloc('E');
  126.         }
  127.     }
  128. }
  129.  
  130. VOID
  131. link()
  132. {
  133.     register c;
  134.  
  135.     if ((c=endline()) == 0) { return; }
  136.     switch (c) {
  137.  
  138.     case 'X':
  139.         radix = 16;
  140.         break;
  141.  
  142.     case 'D':
  143.         radix = 10;
  144.         break;
  145.  
  146.     case 'Q':
  147.         radix = 8;
  148.         break;
  149.  
  150.     case 'H':
  151.         if (pass == 0) {
  152.             newhead();
  153.         } else {
  154.             if (hp == 0) {
  155.                 hp = headp;
  156.             } else {
  157.                 hp = hp->h_hp;
  158.             }
  159.         }
  160.         break;
  161.  
  162.     case 'M':
  163.         if (pass == 0)
  164.             module();
  165.         break;
  166.  
  167.     case 'A':
  168.         if (pass == 0)
  169.             newarea();
  170.         break;
  171.  
  172.     case 'S':
  173.         if (pass == 0)
  174.             newsym();
  175.         break;
  176.  
  177.     case 'T':
  178.     case 'R':
  179.         if (pass == 0)
  180.             break;
  181.         reloc(c);
  182.         break;
  183.  
  184.     default:
  185.         break;
  186.     }
  187.     if (c == 'X' || c == 'D' || c == 'Q') {
  188.         if ((c = get()) == 'H') {
  189.             hilo = 1;
  190.         } else
  191.         if (c == 'L') {
  192.             hilo = 0;
  193.         }
  194.     }
  195. }
  196.  
  197. VOID
  198. map()
  199. {
  200.     register i;
  201.     register struct head *hdp;
  202.  
  203.     /*
  204.      * Open Map File
  205.      */
  206.     mfp = afile(linkp->f_idp, "map", 1);
  207.     /*
  208.      * Output Map Area Lists
  209.      */
  210.     page = 0;
  211.     lop  = NLPP;
  212.     slew(mfp);
  213.     ap = areap;
  214.     while (ap) {
  215.         lstarea(ap);
  216.         ap = ap->a_ap;
  217.     }
  218.     /*
  219.      * List Linked Files
  220.      */
  221.     newpag(mfp);
  222.     fprintf(mfp, "\nFiles Linked      [ module(s) ]\n\n");
  223.     hdp = headp;
  224.     filep = linkp;
  225.     while (filep) {
  226.         fprintf(mfp, "%-16s", filep->f_idp);
  227.         i = 0;
  228.         while (hdp->h_lfile == filep) {
  229.             if (i % 5) {
  230.                 fprintf(mfp, ", %8.8s", hdp->m_id);
  231.             } else {
  232.                 if (i) {
  233.                 fprintf(mfp, ",\n%20s%8.8s", "", hdp->m_id);
  234.                 } else {
  235.                 fprintf(mfp, "  [ %8.8s", hdp->m_id);
  236.                 }
  237.             }
  238.             hdp = hdp->h_hp;
  239.             i++;
  240.         }
  241.         if (i)
  242.             fprintf(mfp, " ]");
  243.         fprintf(mfp, "\n");
  244.         filep = filep->f_flp;
  245.     }
  246.     /*
  247.      * List Base Address Definitions
  248.      */
  249.     if (basep) {
  250.         newpag(mfp);
  251.         fprintf(mfp, "\nUser Base Address Definitions\n\n");
  252.         bsp = basep;
  253.         while (bsp) {
  254.             fprintf(mfp, "%s\n", bsp->b_strp);
  255.             bsp = bsp->b_base;
  256.         }
  257.     }
  258.     /*
  259.      * List Global Definitions
  260.      */
  261.     if (globlp) {
  262.         newpag(mfp);
  263.         fprintf(mfp, "\nUser Global Definitions\n\n");
  264.         gsp = globlp;
  265.         while (gsp) {
  266.             fprintf(mfp, "%s\n", gsp->g_strp);
  267.             gsp = gsp->g_globl;
  268.         }
  269.     }
  270.     fprintf(mfp, "\n\f");
  271.     symdef(mfp);
  272.     fclose(mfp);
  273. }
  274.  
  275. int
  276. parse()
  277. {
  278.     register c;
  279.     char fid[NINPUT];
  280.  
  281.     while (c = getnb()) {
  282.         if ( c == '-') {
  283.             while (ctype[c=get()] == LETTER) {
  284.                 switch(c) {
  285.  
  286.                 case 'i':
  287.                 case 'I':
  288.                     oflag = 1;
  289.                     break;
  290.  
  291.                 case 's':
  292.                 case 'S':
  293.                     oflag = 2;
  294.                     break;
  295.  
  296.                 case 'm':
  297.                 case 'M':
  298.                     ++mflag;
  299.                     break;
  300.  
  301.                 case 'x':
  302.                 case 'X':
  303.                     xflag = 0;
  304.                     break;
  305.  
  306.                 case 'q':
  307.                 case 'Q':
  308.                     xflag = 1;
  309.                     break;
  310.  
  311.                 case 'd':
  312.                 case 'D':
  313.                     xflag = 2;
  314.                     break;
  315.  
  316.                 case 'e':
  317.                 case 'E':
  318.                     return(1);
  319.  
  320.                 case 'n':
  321.                 case 'N':
  322.                     pflag = 0;
  323.                     break;
  324.  
  325.                 case 'p':
  326.                 case 'P':
  327.                     pflag = 1;
  328.                     break;
  329.  
  330.                 case 'b':
  331.                 case 'B':
  332.                     bassav();
  333.                     return(0);
  334.  
  335.                 case 'g':
  336.                 case 'G':
  337.                     gblsav();
  338.                     return(0);
  339.  
  340.                 default:
  341.                     fprintf(stderr, "Invalid option\n");
  342.                     exit(1);
  343.                 }
  344.             }
  345.         } else
  346.         if (ctype[c] == LETTER || ctype[c] == DIGIT) {
  347.             if (linkp == NULL) {
  348.                 linkp = (struct lfile *)
  349.                     new (sizeof (struct lfile));
  350.                 lfp = linkp;
  351.             } else {
  352.                 lfp->f_flp = (struct lfile *)
  353.                         new (sizeof (struct lfile));
  354.                 lfp = lfp->f_flp;
  355.             }
  356.             getfid(fid, c);
  357.             lfp->f_idp = (char *) new (strlen(fid)+1);
  358.             strcpy(lfp->f_idp, fid);
  359.             lfp->f_type = F_REL;
  360.         } else
  361.         if (c == ';') {
  362.             return(0);
  363.         } else
  364.         if (c == ',') {
  365.             ;
  366.         } else {
  367.             fprintf(stderr, "Invalid input");
  368.             exit(1);
  369.         }
  370.     }
  371.     return(0);
  372. }
  373.  
  374. /*
  375.  * Base string save
  376.  */
  377. VOID
  378. bassav()
  379. {
  380.     if (basep == NULL) {
  381.         basep = (struct base *)
  382.             new (sizeof (struct base));
  383.         bsp = basep;
  384.     } else {
  385.         bsp->b_base = (struct base *)
  386.                 new (sizeof (struct base));
  387.         bsp = bsp->b_base;
  388.     }
  389.     unget(getnb());
  390.     bsp->b_strp = (char *) new (strlen(ip)+1);
  391.     strcpy(bsp->b_strp, ip);
  392. }
  393.     
  394. VOID
  395. setbas()
  396. {
  397.     register v;
  398.     char id[NCPS];
  399.  
  400.     bsp = basep;
  401.     while (bsp) {
  402.         ip = bsp->b_strp;
  403.         getid(id, -1);
  404.         if (getnb() == '=') {
  405.             v = expr(0);
  406.             for (ap = areap; ap != NULL; ap = ap->a_ap) {
  407.                 if (symeq(id, ap->a_id))
  408.                     break;
  409.             }
  410.             if (ap == NULL) {
  411.                 fprintf(stderr,
  412.                 "No definition of area %s\n", id);
  413.             } else {
  414.                 ap->a_addr = v;
  415.             }
  416.         } else {
  417.             fprintf(stderr, "No '=' in base expression");
  418.         }
  419.         bsp = bsp->b_base;
  420.     }
  421. }
  422.  
  423. /*
  424.  * Global string save
  425.  */
  426. VOID
  427. gblsav()
  428. {
  429.     if (globlp == NULL) {
  430.         globlp = (struct globl *)
  431.             new (sizeof (struct globl));
  432.         gsp = globlp;
  433.     } else {
  434.         gsp->g_globl = (struct globl *)
  435.                 new (sizeof (struct globl));
  436.         gsp = gsp->g_globl;
  437.     }
  438.     unget(getnb());
  439.     gsp->g_strp = (char *) new (strlen(ip)+1);
  440.     strcpy(gsp->g_strp, ip);
  441. }
  442.     
  443. VOID
  444. setgbl()
  445. {
  446.     register v;
  447.     register struct sym *sp;
  448.     char id[NCPS];
  449.  
  450.     gsp = globlp;
  451.     while (gsp) {
  452.         ip = gsp->g_strp;
  453.         getid(id, -1);
  454.         if (getnb() == '=') {
  455.             v = expr(0);
  456.             sp = lkpsym(id, 0);
  457.             if (sp == NULL) {
  458.                 fprintf(stderr,
  459.                 "No definition of symbol %s\n", id);
  460.             } else {
  461.                 if (sp->s_flag & S_DEF) {
  462.                     fprintf(stderr,
  463.                     "Redefinition of symbol %s\n", id);
  464.                     sp->s_axp = NULL;
  465.                 }
  466.                 sp->s_addr = v;
  467.                 sp->s_type |= S_DEF;
  468.             }
  469.         } else {
  470.             fprintf(stderr, "No '=' in global expression");
  471.         }
  472.         gsp = gsp->g_globl;
  473.     }
  474. }
  475.  
  476. FILE *
  477. afile(fn, ft, wf)
  478. char *fn;
  479. char *ft;
  480. {
  481.     register char *p1, *p2, *p3;
  482.     register c;
  483.     FILE *fp;
  484.     char fb[FILSPC];
  485.  
  486.     p1 = fn;
  487.     p2 = fb;
  488.     p3 = ft;
  489.     while ((c = *p1++) && c != '.') {
  490.         if (p2 < &fb[FILSPC-4])
  491.             *p2++ = c;
  492.     }
  493.     *p2++ = '.';
  494.     if (*p3 == 0) {
  495.         if (c == '.') {
  496.             p3 = p1;
  497.         } else {
  498.             p3 = "rel";
  499.         }
  500.     }
  501.     while (c = *p3++) {
  502.         if (p2 < &fb[FILSPC-1])
  503.             *p2++ = c;
  504.     }
  505.     *p2++ = 0;
  506.     if ((fp = fopen(fb, wf?"w":"r")) == NULL) {
  507.         fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open");
  508.         exit(1);
  509.     }
  510.     return (fp);
  511. }
  512.  
  513. char *usetxt[] = {
  514.     "Startup:",
  515.     "  -c                           Command line input",
  516.     "  -f   file [.lnk]             File input",
  517.     "Usage: [-Options] file [file ...]",
  518.     "  -p   Prompt and echo of file.ln